Merge 16- and 32-bit ico support from the stable branch. (#61179)
authorMatthias Clasen <matthiasc@src.gnome.org>
Fri, 1 Feb 2002 23:43:07 +0000 (23:43 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Fri, 1 Feb 2002 23:43:07 +0000 (23:43 +0000)
        * io-ico.c: Merge 16- and 32-bit ico support from the stable
        branch.  (#61179)

        * io-gif.c: Recomposite all images if the animation size changes
        while loading.  (#70055)

        * gdk-pixbuf.c (gdk-pixbuf-fill): Make it work for subpixbufs.
        (#70055)

gdk-pixbuf/ChangeLog
gdk-pixbuf/gdk-pixbuf.c
gdk-pixbuf/io-gif.c
gdk-pixbuf/io-ico.c

index 3853731e6b44f5c830fcf435acf39f07dedc8ef4..eb89d95db8ab3bbe57e490d991ad35a5fb041d41 100644 (file)
@@ -1,3 +1,14 @@
+2002-02-01  Matthias Clasen  <matthiasc@poet.de>
+
+       * io-ico.c: Merge 16- and 32-bit ico support from the stable 
+       branch.  (#61179)
+
+       * io-gif.c: Recomposite all images if the animation size changes
+       while loading.  (#70055)
+
+       * gdk-pixbuf.c (gdk-pixbuf-fill): Make it work for subpixbufs. 
+       (#70055)
+
 Sat Jan 19 20:49:20 2002  Manish Singh  <yosh@gimp.org>
 
        * io-jpeg.c, io-png.c: Made sure all the error cases involving
index 5928ae0dfbda7ed012279111d26afeef30135a76..93c4c6db2c982d109df5b7cfb3c66f4f6f1846dc 100644 (file)
@@ -428,7 +428,9 @@ gdk_pixbuf_fill (GdkPixbuf *pixbuf,
         guchar *pixels;
         gboolean all_the_same = FALSE;
         guint r, g, b, a;
-        
+        guchar *p;
+        gint n;
+
         g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
 
         if (pixbuf->width == 0 || pixbuf->height == 0)
@@ -449,12 +451,13 @@ gdk_pixbuf_fill (GdkPixbuf *pixbuf,
         }
         
         if (all_the_same) {
-                memset (pixels, r,
-                        pixbuf->rowstride * pixbuf->height);
+                if (pixbuf->has_alpha)
+                        memset (pixels, r, pixbuf->width * 4);
+                else
+                        memset (pixels, r, pixbuf->width * 3);
+
         } else {
-                guchar *p;
                 guchar  c[4];
-                gint    n;
 
                 c[0] = r; c[1] = g; c[2] = b; c[3] = a;
                 
@@ -472,12 +475,12 @@ gdk_pixbuf_fill (GdkPixbuf *pixbuf,
                         } while (--n);
                 }
 
-                p = pixels;
-                n = pixbuf->height - 1;
-                while (n--) {
-                        p += pixbuf->rowstride;
-                        memcpy (p, pixels, pixbuf->width * pixbuf->n_channels);
-                }
+        }
+        p = pixels;
+        n = pixbuf->height - 1;
+        while (n--) {
+                p += pixbuf->rowstride;
+                memcpy (p, pixels, pixbuf->width * pixbuf->n_channels);
         }
 }
 
index c6bb34eccf77c508f601d2ef9a5514f70dfdadf9..c01a58ff078645bca62cfe12ced4355f7f9047e4 100644 (file)
@@ -725,6 +725,14 @@ gif_fill_in_lines (GifContext *context, guchar *dest, guchar v)
        }
 }
 
+static void
+set_need_recomposite (gpointer data, gpointer user_data)
+{
+        GdkPixbufFrame *frame = (GdkPixbufFrame *)data;
+        frame->need_recomposite = TRUE;
+}
+
+
 static int
 gif_get_lzw (GifContext *context)
 {
@@ -802,6 +810,9 @@ gif_get_lzw (GifContext *context)
                                 gdk_pixbuf_get_width (context->frame->pixbuf);
                         h = context->frame->y_offset +
                                 gdk_pixbuf_get_height (context->frame->pixbuf);
+                        if (w  > context->animation->width || h > context->animation->height) {
+                                g_list_foreach (context->animation->frames, set_need_recomposite, NULL);
+                        }
                         if (w > context->animation->width)
                                 context->animation->width = w;
                         if (h > context->animation->height)
index 4e871fb9df7c94866cd87ee4a88dce22c48c2d09..412ea319dacf63d1f9db23f0185db524ad79cb2f 100644 (file)
@@ -139,8 +139,11 @@ struct ico_progressive_state {
        gint Lines;             /* # of finished lines */
 
        gint Type;              /*  
+                                  32 = RGBA
                                   24 = RGB
+                                  16 = 555 RGB
                                   8 = 8 bit colormapped
+                                  4 = 4 bpp colormapped
                                   1  = 1 bit bitonal 
                                 */
 
@@ -247,9 +250,9 @@ static void DecodeHeader(guchar *Data, gint Bytes,
        /* Step 1: The ICO header */
  
        IconCount = (Data[5] << 8) + (Data[4]);
+       
        State->HeaderSize = 6 + IconCount*16;
-       
+
        if (State->HeaderSize>State->BytesInHeaderBuf) {
                State->HeaderBuf=g_try_realloc(State->HeaderBuf,State->HeaderSize);
                if (!State->HeaderBuf) {
@@ -396,17 +399,26 @@ static void DecodeHeader(guchar *Data, gint Bytes,
        g_assert (State->Header.width > 0);
        g_assert (State->Header.height > 0);
 
-       if (State->Type == 24)
+        if (State->Type == 32)
+                State->LineWidth = State->Header.width * 4;
+        else if (State->Type == 24)
                State->LineWidth = State->Header.width * 3;
-       if (State->Type == 8)
+        else if (State->Type == 16)
+                State->LineWidth = State->Header.height * 2;
+        else if (State->Type == 8)
                State->LineWidth = State->Header.width * 1;
-       if (State->Type == 4) {
+        else if (State->Type == 4)
                State->LineWidth = (State->Header.width+1)/2;
-       }
-       if (State->Type == 1) {
+        else if (State->Type == 1) {
                State->LineWidth = State->Header.width / 8;
                if ((State->Header.width & 7) != 0)
                        State->LineWidth++;
+        } else {
+          g_set_error (error,
+                       GDK_PIXBUF_ERROR,
+                       GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                       _("Unsupported icon type"));
+          return;
        }
 
        /* Pad to a 32 bit boundary */
@@ -421,8 +433,8 @@ static void DecodeHeader(guchar *Data, gint Bytes,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Not enough memory to load icon"));
+                       return;
                }
-               return;
        }
 
        g_assert(State->LineBuf != NULL);
@@ -513,6 +525,29 @@ gboolean gdk_pixbuf__ico_image_stop_load(gpointer data,
         return TRUE;
 }
 
+static void
+OneLine32 (struct ico_progressive_state *context)
+{
+        gint X;
+        guchar *Pixels;
+
+        X = 0;
+        if (context->Header.Negative == 0)
+                Pixels = (context->pixbuf->pixels +
+                          context->pixbuf->rowstride *
+                          (context->Header.height - context->Lines - 1));
+        else
+                Pixels = (context->pixbuf->pixels +
+                          context->pixbuf->rowstride *
+                          context->Lines);
+        while (X < context->Header.width) {
+                Pixels[X * 4 + 0] = context->LineBuf[X * 4 + 2];
+                Pixels[X * 4 + 1] = context->LineBuf[X * 4 + 1];
+                Pixels[X * 4 + 2] = context->LineBuf[X * 4 + 0];
+                Pixels[X * 4 + 3] = context->LineBuf[X * 4 + 3];
+                X++;
+        }
+}
 
 static void OneLine24(struct ico_progressive_state *context)
 {
@@ -537,6 +572,44 @@ static void OneLine24(struct ico_progressive_state *context)
 
 }
 
+static void
+OneLine16 (struct ico_progressive_state *context)
+{
+        int i;
+        guchar *pixels;
+        guchar *src;
+
+        if (context->Header.Negative == 0)
+                pixels = (context->pixbuf->pixels +
+                          context->pixbuf->rowstride * (context->Header.height - context->Lines - 1));
+        else
+                pixels = (context->pixbuf->pixels +
+                          context->pixbuf->rowstride * context->Lines);
+
+        src = context->LineBuf;
+
+        for (i = 0; i < context->Header.width; i++) {
+                int v, r, g, b;
+
+                v = (int) src[0] | ((int) src[1] << 8);
+                src += 2;
+
+                /* Extract 5-bit RGB values */
+
+                r = (v >> 10) & 0x1f;
+                g = (v >> 5) & 0x1f;
+                b = v & 0x1f;
+
+                /* Fill the rightmost bits to form 8-bit values */
+
+                *pixels++ = (r << 3) | (r >> 2);
+                *pixels++ = (g << 3) | (g >> 2);
+                *pixels++ = (b << 3) | (b >> 2);
+                pixels++; /* skip alpha channel */
+        }
+}
+
+
 static void OneLine8(struct ico_progressive_state *context)
 {
        gint X;
@@ -674,19 +747,22 @@ static void OneLine(struct ico_progressive_state *context)
        }
                
        if (context->Lines <context->Header.height) {           
-
-               if (context->Type == 24)
+                if (context->Type == 32)
+                        OneLine32 (context);
+               else if (context->Type == 24)
                        OneLine24(context);
-               if (context->Type == 8)
+                else if (context->Type == 16)
+                        OneLine16 (context);
+               else if (context->Type == 8)
                        OneLine8(context);
-               if (context->Type == 4)
+               else if (context->Type == 4)
                        OneLine4(context);
-               if (context->Type == 1)
+               else if (context->Type == 1)
                        OneLine1(context);
+               else 
+                       g_assert_not_reached ();
        } else
-       {
                OneLineTransp(context);
-       }
        
        context->Lines++;
        if (context->Lines>=context->Header.height) {